package utils

import (
	"errors"
	"sync"

	"gitee.com/war2001/NiuMaEasyGo/model"
	"github.com/silenceper/wechat/v2"
	"github.com/silenceper/wechat/v2/cache"
	"github.com/silenceper/wechat/v2/miniprogram"
	"github.com/silenceper/wechat/v2/miniprogram/config"
	"github.com/silenceper/wechat/v2/officialaccount"
	offConfig "github.com/silenceper/wechat/v2/officialaccount/config"
)

// WechatUtil 微信工具类
type WechatUtil struct {
	configService model.WechatConfigService
	redisCache    cache.Cache

	// 缓存已创建的实例，避免重复创建
	miniProgramClients     map[uint]*miniprogram.MiniProgram
	officialAccountClients map[uint]*officialaccount.OfficialAccount
	mu                     sync.RWMutex
}

// NewWechatUtil 创建微信工具类
func NewWechatUtil(configService model.WechatConfigService, redisCache cache.Cache) *WechatUtil {
	return &WechatUtil{
		configService:          configService,
		redisCache:             redisCache,
		miniProgramClients:     make(map[uint]*miniprogram.MiniProgram),
		officialAccountClients: make(map[uint]*officialaccount.OfficialAccount),
	}
}

// GetMiniProgram 获取小程序实例
func (u *WechatUtil) GetMiniProgram(tenantID uint, configID ...uint) (*miniprogram.MiniProgram, error) {
	var wechatConfig *model.WechatConfig
	var err error

	// 如果指定了配置ID，则使用指定的配置
	if len(configID) > 0 && configID[0] > 0 {
		wechatConfig, err = u.configService.GetByID(configID[0])
		if err != nil {
			return nil, err
		}

		// 验证配置类型和商户ID
		if wechatConfig.Type != "mini_program" {
			return nil, errors.New("配置类型不是小程序")
		}
		if wechatConfig.TenantID != tenantID {
			return nil, errors.New("配置不属于该商户")
		}
	} else {
		// 否则使用默认配置
		wechatConfig, err = u.configService.GetDefault(tenantID, "mini_program")
		if err != nil {
			return nil, err
		}
	}

	// 检查缓存中是否已存在该实例
	u.mu.RLock()
	if client, ok := u.miniProgramClients[wechatConfig.ID]; ok {
		u.mu.RUnlock()
		return client, nil
	}
	u.mu.RUnlock()

	// 创建小程序实例
	wc := wechat.NewWechat()
	mpConfig := &config.Config{
		AppID:     wechatConfig.AppID,
		AppSecret: wechatConfig.AppSecret,
		Cache:     u.redisCache,
	}
	mp := wc.GetMiniProgram(mpConfig)

	// 缓存实例
	u.mu.Lock()
	u.miniProgramClients[wechatConfig.ID] = mp
	u.mu.Unlock()

	return mp, nil
}

// GetOfficialAccount 获取公众号实例
func (u *WechatUtil) GetOfficialAccount(tenantID uint, configID ...uint) (*officialaccount.OfficialAccount, error) {
	var wechatConfig *model.WechatConfig
	var err error

	// 如果指定了配置ID，则使用指定的配置
	if len(configID) > 0 && configID[0] > 0 {
		wechatConfig, err = u.configService.GetByID(configID[0])
		if err != nil {
			return nil, err
		}

		// 验证配置类型和商户ID
		if wechatConfig.Type != "official_account" {
			return nil, errors.New("配置类型不是公众号")
		}
		if wechatConfig.TenantID != tenantID {
			return nil, err
		}
	} else {
		// 否则使用默认配置
		wechatConfig, err = u.configService.GetDefault(tenantID, "official_account")
		if err != nil {
			return nil, err
		}
	}

	// 检查缓存中是否已存在该实例
	u.mu.RLock()
	if client, ok := u.officialAccountClients[wechatConfig.ID]; ok {
		u.mu.RUnlock()
		return client, nil
	}
	u.mu.RUnlock()

	// 创建公众号实例
	wc := wechat.NewWechat()
	oaConfig := &offConfig.Config{
		AppID:          wechatConfig.AppID,
		AppSecret:      wechatConfig.AppSecret,
		Token:          wechatConfig.Token,
		EncodingAESKey: wechatConfig.EncodingAESKey,
		Cache:          u.redisCache,
	}
	oa := wc.GetOfficialAccount(oaConfig)

	// 缓存实例
	u.mu.Lock()
	u.officialAccountClients[wechatConfig.ID] = oa
	u.mu.Unlock()

	return oa, nil
}

// ClearCache 清除缓存的微信实例
func (u *WechatUtil) ClearCache(configID uint) {
	u.mu.Lock()
	defer u.mu.Unlock()

	delete(u.miniProgramClients, configID)
	delete(u.officialAccountClients, configID)
}

// ClearAllCache 清除所有缓存的微信实例
func (u *WechatUtil) ClearAllCache() {
	u.mu.Lock()
	defer u.mu.Unlock()

	u.miniProgramClients = make(map[uint]*miniprogram.MiniProgram)
	u.officialAccountClients = make(map[uint]*officialaccount.OfficialAccount)
}
